package org.shiro.demo.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.shiro.demo.dao.util.Pagination;
import org.shiro.demo.dao.util.QueryCondition;
import org.shiro.demo.disruptor.DisruptorUtils;
import org.shiro.demo.disruptor.TradeTransaction;
import org.shiro.demo.disruptor.TradeTransactionEventTranslator;
import org.shiro.demo.entity.Administrator;
import org.shiro.demo.entity.BufferSum;
import org.shiro.demo.entity.GroupOrder;
import org.shiro.demo.entity.Order;
import org.shiro.demo.entity.OrderBuffer;
import org.shiro.demo.entity.Pay2Manager;
import org.shiro.demo.entity.ResponseResult;
import org.shiro.demo.entity.Store;
import org.shiro.demo.entity.Ticket;
import org.shiro.demo.entity.WeixinAccount;
import org.shiro.demo.service.IBaseService;
import org.shiro.demo.service.IOrderBufferService;
import org.shiro.demo.service.impl.OrderBufferServiceImpl;
import org.shiro.demo.util.UUIDCreator;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/orderbuffer")
public class OrderBufferController {

	@Resource(name = "disruptorUtils")
	DisruptorUtils disruptorUtils;

	@Resource(name = "baseService")
	IBaseService baseService;

	@Resource(name = "orderBufferService")
	IOrderBufferService orderBufferService;

	private DateTimeFormatter dayFormat = DateTimeFormat.forPattern("yyyy-MM-dd");

	private SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");

	/**
	 * 
	 * @param date
	 *            查询时间
	 * @return
	 * @throws ParseException
	 */
	@RequestMapping(value = "/getByDay")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("manager")
	public Object getByDay(@RequestParam(value = "date") String date, @RequestParam(value = "pageSize") int pageSize, @RequestParam(value = "cpage") int cpage) throws ParseException {
		ResponseResult rr = new ResponseResult();
		try {
			Object subject = SecurityUtils.getSubject().getPrincipal();

			Administrator manager = (Administrator) subject;

			List<QueryCondition> queryConditions = new ArrayList<QueryCondition>();

			queryConditions.add(new QueryCondition("operator", QueryCondition.EQ, manager.getPhone()));
			// queryConditions.add(new QueryCondition("bufferTime",
			// QueryCondition.LK, sf.parse(date)+"%"));
			org.joda.time.DateTime now = DateTime.parse(date, dayFormat);
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.GT, now.toDate()));
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.LT, now.plusDays(1).toDate()));

			Pagination<OrderBuffer> pagination = new Pagination<OrderBuffer>();

			pagination = baseService.getPagination(OrderBuffer.class, queryConditions, "order by o.bufferTime desc", cpage, pageSize);

			rr.setCode(1);
			rr.setInfo("success");
			rr.setObject(pagination);

			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			return rr;
		}
	}

	/**
	 * 
	 * @param date
	 *            查询时间
	 * @return
	 * @throws ParseException
	 */
	@RequestMapping(value = "/getByMonth")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("manager")
	public Object getByMonth(@RequestParam(value = "date") String date, @RequestParam(value = "pageSize") int pageSize, @RequestParam(value = "cpage") int cpage) throws ParseException {
		ResponseResult rr = new ResponseResult();
		try {
			Object subject = SecurityUtils.getSubject().getPrincipal();

			Administrator manager = (Administrator) subject;

			List<QueryCondition> queryConditions = new ArrayList<QueryCondition>();

			queryConditions.add(new QueryCondition("operator", QueryCondition.EQ, manager.getPhone()));
			// queryConditions.add(new QueryCondition("bufferTime",
			// QueryCondition.LK, sf.parse(date)+"%"));
			org.joda.time.DateTime now = DateTime.parse(date + "-01", dayFormat);
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.GE, now.toDate()));
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.LT, now.plusMonths(1).toDate()));

			Pagination<OrderBuffer> pagination = new Pagination<OrderBuffer>();

			pagination = baseService.getPagination(OrderBuffer.class, queryConditions, "order by o.bufferTime desc", cpage, pageSize);

			rr.setCode(1);
			rr.setInfo("success");
			rr.setObject(pagination);

			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			return rr;
		}
	}

	/**
	 * 
	 * @param date
	 *            查询时间
	 * @return
	 * @throws ParseException
	 */
	@RequestMapping(value = "/getSuperDay")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object getSuperDay(@RequestParam(value = "date") String date, @RequestParam(value = "pageSize") int pageSize, @RequestParam(value = "cpage") int cpage) throws ParseException {
		ResponseResult rr = new ResponseResult();
		try {

			List<QueryCondition> queryConditions = new ArrayList<QueryCondition>();

			org.joda.time.DateTime now = DateTime.parse(date, dayFormat);
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.GT, now.toDate()));
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.LT, now.plusDays(1).toDate()));

			Pagination<OrderBuffer> pagination = new Pagination<OrderBuffer>();

			pagination = baseService.getPagination(OrderBuffer.class, queryConditions, "order by o.bufferTime desc", cpage, pageSize);

			rr.setCode(1);
			rr.setInfo("success");
			rr.setObject(pagination);

			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			return rr;
		}
	}

	/**
	 * 
	 * @param date
	 *            查询时间
	 * @return
	 * @throws ParseException
	 */
	@RequestMapping(value = "/getSuperMonth")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object getSuperMonth(@RequestParam(value = "date") String date, @RequestParam(value = "pageSize") int pageSize, @RequestParam(value = "cpage") int cpage) throws ParseException {
		ResponseResult rr = new ResponseResult();
		try {

			List<QueryCondition> queryConditions = new ArrayList<QueryCondition>();

			org.joda.time.DateTime now = DateTime.parse(date + "-01", dayFormat);
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.GE, now.toDate()));
			queryConditions.add(new QueryCondition("bufferTime", QueryCondition.LT, now.plusMonths(1).toDate()));

			Pagination<OrderBuffer> pagination = new Pagination<OrderBuffer>();

			pagination = baseService.getPagination(OrderBuffer.class, queryConditions, "order by o.bufferTime desc", cpage, pageSize);

			rr.setCode(1);
			rr.setInfo("success");
			rr.setObject(pagination);

			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			return rr;
		}
	}

	/**
	 * 店长查询 提货详情
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/get")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles(value = "manager")
	public Object get(@RequestParam(value = "uuid") String uuid) {
		ResponseResult rr = new ResponseResult();
		try {
			Administrator admin = (Administrator) SecurityUtils.getSubject().getPrincipal();
			if (StringUtils.isEmpty(uuid)) {
				rr.setCode(0);
				rr.setInfo("订单号不能为空");
				return rr;
			}
			char start = uuid.charAt(0);
			List<QueryCondition> list = new ArrayList<QueryCondition>();
			list.add(new QueryCondition("uuid", QueryCondition.EQ, uuid));
			switch (start) {
			case 'o':
				Order order = (Order) baseService.getSingleResult(Order.class, list);
				if (order.getOrderProp().getId() != 3L || !order.getOperator().equals(admin.getPhone())) {
					rr.setInfo("订单非你处理过的");
					return rr;
				}
				rr.setObject(order);
				break;
			case 'g':
				GroupOrder gorder = (GroupOrder) baseService.getSingleResult(GroupOrder.class, list);
				if (gorder.getOrderProp().getId() != 3L || !gorder.getOperator().equals(admin.getPhone())) {
					rr.setInfo("订单非你处理过的");
					return rr;
				}
				rr.setObject(gorder);
				break;
			case 't':
				Ticket ticket = (Ticket) baseService.getSingleResult(Ticket.class, list);
				if (ticket.getOrderProp().getId() != 3L || !ticket.getOperator().equals(admin.getPhone())) {
					rr.setInfo("订单非你处理过的");
					return rr;
				}
				rr.setObject(ticket);
				break;

			default:
				rr.setInfo("找不到订单");
				break;
			}

			rr.setCode(1);
			rr.setInfo("success");
			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo("内部出错");
			return rr;
		}
	}

	/**
	 * 超级管理员查询 提货详情
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/superGet")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object superGet(@RequestParam(value = "uuid") String uuid) {
		ResponseResult rr = new ResponseResult();
		try {

			if (StringUtils.isEmpty(uuid)) {
				rr.setCode(0);
				rr.setInfo("订单号不能为空");
				return rr;
			}
			char start = uuid.charAt(0);
			List<QueryCondition> list = new ArrayList<QueryCondition>();
			list.add(new QueryCondition("uuid", QueryCondition.EQ, uuid));
			switch (start) {
			case 'o':
				Order order = (Order) baseService.getSingleResult(Order.class, list);

				rr.setObject(order);
				break;
			case 'g':
				GroupOrder gorder = (GroupOrder) baseService.getSingleResult(GroupOrder.class, list);

				rr.setObject(gorder);
				break;
			case 't':
				Ticket ticket = (Ticket) baseService.getSingleResult(Ticket.class, list);

				rr.setObject(ticket);
				break;

			default:
				rr.setInfo("找不到订单");
				return rr;

			}

			rr.setCode(1);
			rr.setInfo("success");
			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo("内部出错");
			return rr;
		}
	}

	// -----------汇总列表。。。 针对店长 ---------------------------------------

	/**
	 * 店长看自己的账单
	 * 
	 * 如果 是今天，那么应该去查找 OrderBuffer的表
	 * 
	 * 如果是昨天或者过去时，那么应该去查找 Pay2Manager这张表
	 * 
	 * 
	 * @param date
	 * @return
	 */
	@RequestMapping(value = "/sum")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("manager")
	public Object sum(@RequestParam(value = "date", required = true) String date) {
		ResponseResult rr = new ResponseResult();
		// BufferSum bufferSum = new BufferSum();
		org.joda.time.DateTime bufferDate = null;
		Pay2Manager pay2Manager = new Pay2Manager();
		try {
			bufferDate = DateTime.parse(date, dayFormat);
			// bufferSum.setBufferDay(bufferDate.toDate());
			pay2Manager.setCorrespondingDate(bufferDate.toDate());
			if (bufferDate.isAfterNow()) {
				rr.setInfo("日期将来时");
				return rr;
			}
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo("日期有误");
			return rr;
		}
		Administrator admin = (Administrator) SecurityUtils.getSubject().getPrincipal();
		if (date.equals(FORMAT.format(new Date()))) {// 今天
			pay2Manager = genPay2ManagerFromBuffer(admin.getPhone(), date);
			rr.setInfo("success");
			rr.setObject(pay2Manager);
			rr.setCode(1);
			return rr;
		}
		// 如果是昨天 或者过去时间..先查表。找不到，那么就 查找 bufferorder表。
		else {
			List<QueryCondition> list = new ArrayList<QueryCondition>();
			list.add(new QueryCondition("correspondingDate", QueryCondition.EQ, bufferDate.toDate()));
			list.add(new QueryCondition("payee", QueryCondition.EQ, admin.getPhone()));// 都是int
			pay2Manager = (Pay2Manager) baseService.getSingleResult(Pay2Manager.class, list);
			// 到orderbuffer 里面去查找..但是不save ，因为 save 动作只能留给
			// super-administrator来执行
			if (pay2Manager == null) {
				genPay2ManagerFromBuffer(admin.getPhone(), date);
			}
			rr.setInfo("success");
			rr.setObject(pay2Manager);
			rr.setCode(1);
			return rr;

		}
	}

	private Pay2Manager genPay2ManagerFromBuffer(String phone, String date) {
		List<OrderBuffer> buffers = orderBufferService.getAndCache(phone, date);
		double tm = 0;
		double gm = 0;
		double om = 0;
		int t = 0;
		int g = 0;
		int o = 0;

		for (OrderBuffer orderBuffer : buffers) {
			switch (orderBuffer.getOrderType()) {
			case 1:
				om += orderBuffer.getMoney();
				o++;
				break;
			case 2:
				gm += orderBuffer.getMoney();
				g++;
				break;
			case 3:
				tm += orderBuffer.getMoney();
				t++;
				break;

			default:
				break;
			}

		}

		StringBuilder sb = new StringBuilder();
		sb.append("o_" + o + "_" + om + ";");
		sb.append("g_" + g + "_" + gm + ";");
		sb.append("t_" + t + "_" + tm);
		Pay2Manager pay2Manager = new Pay2Manager();
		pay2Manager.setAtmed(false);
		pay2Manager.setDetail(sb.toString());
		pay2Manager.setMoney(om + gm + tm);
		pay2Manager.setPayee(phone);
		return pay2Manager;
	}

	/**
	 * 超级管理员 看店长的账单
	 * 
	 * @param date
	 * @return
	 */
	@RequestMapping(value = "/superStoreSum")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object superStoreSum(@RequestParam(value = "date", required = true) String date, @RequestParam(value = "storeId", required = true) int storeId) {
		ResponseResult rr = new ResponseResult();
		org.joda.time.DateTime bufferDate = null;
		Pay2Manager pay2Manager = new Pay2Manager();
		try {
			bufferDate = DateTime.parse(date, dayFormat);
			pay2Manager.setCorrespondingDate(bufferDate.toDate());
			if (bufferDate.isAfterNow()) {
				rr.setInfo("日期将来时");
				return rr;
			}
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo("日期有误");
			return rr;
		}
		// 拿到店长
		Store store = baseService.getById(Store.class, storeId);
		if (store == null) {
			rr.setInfo("门店不存在");
			return rr;
		}
		Collection<Administrator> collections = store.getManagers();
		if (collections.size() > 1) {
			rr.setInfo("店长不止一个人");
			return rr;
		}
		if (collections.size() < 1) {
			rr.setInfo("没有店长");
			return rr;
		}
		Iterator<Administrator> admins = collections.iterator();
		Administrator manager = admins.next();
		if (date.equals(FORMAT.format(new Date()))) {// 今天
			pay2Manager = genPay2ManagerFromBuffer(manager.getPhone(), date);
			rr.setInfo("success");
			rr.setObject(pay2Manager);
			rr.setCode(1);
			return rr;
		} else {// 昨天 或者过去式
			List<QueryCondition> list = new ArrayList<QueryCondition>();
			list.add(new QueryCondition("correspondingDate", QueryCondition.EQ, bufferDate.toDate()));
			list.add(new QueryCondition("payee", QueryCondition.EQ, manager.getPhone()));// 都是int
			pay2Manager = (Pay2Manager) baseService.getSingleResult(Pay2Manager.class, list);
			// 到orderbuffer 里面去查找.. 然后save ，因为 save 动作只能留给
			// super-administrator的 getPay 来执行来执行
			if (pay2Manager == null) {
				genPay2ManagerFromBuffer(manager.getPhone(), date);
			}
			rr.setInfo("success");
			rr.setObject(pay2Manager);
			rr.setCode(1);
			return rr;
		}
	}

	/**
	 * 超级管理员 看大账单。。慎用
	 * 
	 * @param date
	 * @return
	 */
	@RequestMapping(value = "/superSum")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object superSum(@RequestParam(value = "date", required = true) String date) {
		ResponseResult rr = new ResponseResult();
		BufferSum bufferSum = new BufferSum();
		org.joda.time.DateTime bufferDate = null;
		try {
			bufferDate = DateTime.parse(date, dayFormat);
			bufferSum.setBufferDay(bufferDate.toDate());
			if (bufferDate.isAfterNow()) {
				rr.setInfo("日期将来时");
				return rr;
			}
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo("日期有误");
			return rr;
		}

		bufferSum.setOmoney(getMoney(bufferDate.toDate(), 1));
		bufferSum.setGmoney(getMoney(bufferDate.toDate(), 2));
		bufferSum.setTmoney(getMoney(bufferDate.toDate(), 3));

		rr.setInfo("success");
		rr.setObject(bufferSum);
		rr.setCode(1);
		return rr;
	}

	private double getMoney(Date bufferDate, int orderType) {
		// 使用jpql1
		String jpql1 = "Select sum(o.money) from OrderBuffer o where o.bufferDate=?1  and o.orderType = ?2 ";
		List<Double> moneys1 = baseService.getByJpql(jpql1, bufferDate, orderType);
		Double money1 = moneys1.get(0);
		if (money1 == null) {
			return 0;
		}
		return money1;
	}

	// -----------收款接口，每天打钱。 ---------------------------------------
	/**
	 * 打钱...超级谨慎的 接口
	 * 
	 * @param date
	 *            (String) storeId(int)
	 * 
	 * 
	 * @流程： ① 先检查是否 date正确， 要求 是过去的日期
	 * 
	 *      ② 检查 store 是不是只有一个manager
	 * 
	 *      ③ 检查 manager 是否绑定 微信
	 * 
	 *      ④ 检查 date这一天 对应的storeId 是否已经支付。
	 * 
	 *      ⑤ 算出 这一天 这个manager 提货金额。 从 OrderBuffer 表中 得到。
	 * 
	 *      ⑥ save 一条Pay2Manager到数据库。 给 这个manager 的微信发送一条微信消息。
	 * 
	 *      ⑦ 准备被提现。
	 * @return
	 */
	@RequestMapping(value = "/superPay")
	@ResponseBody
	@RequiresAuthentication
	@RequiresRoles("super-administrator")
	public Object superPay(@RequestParam(value = "date", required = true) String date, @RequestParam(value = "storeId", required = true) int storeId) {
		ResponseResult rr = new ResponseResult();

		try {
			// 流程1 先检查是否 date正确， 要求 是过去的日期
			org.joda.time.DateTime payDate = DateTime.parse(date, dayFormat);
			Date now = new Date();
			org.joda.time.DateTime nowDate = DateTime.parse(FORMAT.format(now), dayFormat);
			if (nowDate.isBefore(payDate) || nowDate.isEqual(payDate)) {
				// 现在的日期 在 支付日期的 之前。。也就是支付日期大于现在的日期。。支付日期 属于将来时
				rr.setInfo("支付日期属于将来时");
				return rr;
			}
			// 流程2 检查 store 是不是只有一个manager
			Store store = baseService.getById(Store.class, storeId);
			Collection<Administrator> collects = store.getManagers();
			if (collects.size() > 1) {
				rr.setInfo("门店 有不止1个店长");
				return rr;
			}

			// 流程3 检查 manager 是否绑定 微信
			Iterator<Administrator> ite = collects.iterator();
			Administrator manager = ite.next();

			WeixinAccount weixinAccount = baseService.getById(WeixinAccount.class, manager.getPhone());
			if (weixinAccount.getOpenid() == null) {
				rr.setInfo("店长没有绑定微信");
				return rr;
			}

			// 流程4 检查 date这一天 对应的storeId 是否已经支付。
			List<QueryCondition> list = new ArrayList<QueryCondition>();
			list.add(new QueryCondition("correspondingDate", QueryCondition.EQ, payDate.toDate()));
			list.add(new QueryCondition("storeId", QueryCondition.EQ, storeId));// 都是int
			Pay2Manager pay2Manager = (Pay2Manager) baseService.getSingleResult(Pay2Manager.class, list);
			if (pay2Manager != null) {
				rr.setInfo("这家店 的 这一天 收入 已经发出");
				return rr;
			}
			// 流程5 算出 这一天 这个manager 提货金额。 从 OrderBuffer 表中 得到。
			// 使用 jql
			String jpql = "Select sum(o.money) from OrderBuffer o where o.bufferDate=?1  and o.operator = ?2 ";
			List<Double> moneys = baseService.getByJpql(jpql, payDate.toDate(), manager.getPhone());
			// System.out.println(moneys.get(0));// 可能是null, 那么就是这天 完全没有收入
			Double money = moneys.get(0);
			if (money == null) {
				rr.setInfo("这家店 的 这一天 提货收入 为零");
				return rr;
			}
			// 流程6 save 一条Pay2Manager到数据库。 给 这个manager 的微信发送一条微信消息。
			Pay2Manager pay2M = new Pay2Manager();
			pay2M.setId("p" + UUIDCreator.getShortUuid());
			pay2M.setAtmed(false);
			pay2M.setCorrespondingDate(payDate.toDate());
			pay2M.setCreateTime(new Date());
			pay2M.setMoney(money);
			pay2M.setPayee(manager.getPhone());
			pay2M.setStoreId(storeId);
			baseService.save(pay2M);
			List<String> openids = new ArrayList<String>();
			openids.add(weixinAccount.getOpenid());

			List<String> userIds = new ArrayList<String>();
			userIds.add(weixinAccount.getPhone());
			// 发送微信
			TradeTransaction tt = new TradeTransaction();
			tt.setContent("您" + payDate.toString() + "有一笔收入，请提现！");
			tt.setCreateTime(pay2M.getCreateTime());
			tt.setOpenids(openids);
			tt.setPrice(money);
			tt.setUserids(userIds);
			tt.setUrl("https://rs88881234.com/chinesejie/getpay?uuid=" + pay2M.getId());
			disruptorUtils.publish(new TradeTransactionEventTranslator(tt));

			rr.setCode(1);
			rr.setInfo("success");
			return rr;
		} catch (Exception e) {
			e.printStackTrace();
			rr.setInfo(e.getMessage());
			return rr;
		}
	}
}
